package cqrtplm.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.NumberUtil;
import cn.hutool.core.util.ObjectUtil;
import com.alibaba.fastjson.JSON;
import com.hustcad.plm.basic.util.TyplmEntityBaseUtil;
import com.hustcad.plm.basic.util.TyplmLoggerUtil;
import com.hustcad.plm.pdm.code.mapper.TyplmCodeBaseMapper;
import com.hustcad.plm.pdm.code.model.dto.TyplmCodeBaseDTO;
import com.hustcad.plm.pdm.code.model.dto.TyplmCodeSerialDTO;
import com.hustcad.plm.pdm.code.model.entity.TyplmCodeBaseDO;
import com.hustcad.plm.pdm.code.model.vo.TyplmClassificationCodeVo;
import com.hustcad.plm.pdm.code.model.vo.TyplmCodeCustomizationStreamVO;
import com.hustcad.plm.pdm.code.service.impl.number.TyplmCodeServiceImpl;
import com.ty.basic.entity.IdentifierEntity;
import com.ty.basic.service.snow.SnowflakeIdComponent;
import com.ty.basic.util.StringUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.annotation.Primary;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;
import tk.mybatis.mapper.entity.Example;

import javax.annotation.Resource;
import java.math.BigInteger;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.regex.Pattern;

@Primary
@Service
@Slf4j
public class RTTyplmCodeServiceImpl extends TyplmCodeServiceImpl {

    @Resource
    private TyplmCodeBaseMapper typlmCodeBaseMapper;
    @Resource
    private SnowflakeIdComponent snowflakeIdComponent;

    /**
     * 删除分类码校验卡控
     * @param codeBaseDTO
     */
    public void saveCodeBaseInfo(TyplmCodeBaseDTO codeBaseDTO) {
        if (!ObjectUtil.isEmpty(codeBaseDTO)) {
//            this.checkSameCodeBaseData(codeBaseDTO);
            TyplmLoggerUtil.debug(log, () -> "saveCodeBaseInfo  ==>  codeBaseDTO =【{}】", () -> new Object[]{JSON.toJSONString(codeBaseDTO)});
            TyplmCodeBaseDO codeBaseDO = this.queryCodeBaseDOByBaseoid(codeBaseDTO.getBaseoid(), codeBaseDTO.getBaseotype());
            if (codeBaseDO == null || ObjectUtil.isEmpty(codeBaseDO)) {
                codeBaseDO = new TyplmCodeBaseDO();
            }

            this.copyProperties(codeBaseDTO, codeBaseDO);
            if (ObjectUtil.isEmpty(codeBaseDO.getOid())) {
                codeBaseDO.setOid(this.snowflakeIdComponent.getInstance().nextId());
                TyplmEntityBaseUtil.fillCommonFieldForCreate(codeBaseDO);
                this.typlmCodeBaseMapper.insert(codeBaseDO);
            } else {
                TyplmEntityBaseUtil.fillCommonFieldForUpdate(codeBaseDO);
                this.typlmCodeBaseMapper.updateByPrimaryKey(codeBaseDO);
                this.updateLastCodeByClass(false, new IdentifierEntity(codeBaseDO.getBaseotype() + ":" + codeBaseDO.getBaseoid()));
            }

            BeanUtil.copyProperties(codeBaseDO, codeBaseDTO);
        }
    }

    private void copyProperties(TyplmCodeBaseDTO codeBaseDTO, TyplmCodeBaseDO codeBaseDO) {
        if (!ObjectUtil.isEmpty(codeBaseDTO)) {
            if (!ObjectUtil.isEmpty(codeBaseDO)) {
                codeBaseDO.setDescription(codeBaseDTO.getDescription());
                codeBaseDO.setName(codeBaseDTO.getName());
                codeBaseDO.setBaseoid(codeBaseDTO.getBaseoid());
                codeBaseDO.setBaseotype(codeBaseDTO.getBaseotype());
                codeBaseDO.setLastcode(codeBaseDTO.getLastcode());
                codeBaseDO.setSeparator(codeBaseDTO.getSeparator());
                codeBaseDO.setObjectnumber(codeBaseDTO.getObjectnumber());
            }
        }
    }

    private TyplmCodeBaseDO queryCodeBaseDOByBaseoid(BigInteger baseoid, String baseotype) {
        Example example = new Example(TyplmCodeBaseDO.class, true, true);
        Example.Criteria criteria = example.createCriteria();
        criteria.andEqualTo("baseoid", baseoid);
        criteria.andEqualTo("baseotype", baseotype);
        List<TyplmCodeBaseDO> result = this.typlmCodeBaseMapper.selectByExample(example);
        TyplmLoggerUtil.debug(log, () -> "queryCodeBaseDOByBaseoid  ==>  result =【{}】", () -> new Object[]{JSON.toJSONString(result)});
        return CollUtil.isNotEmpty(result) ? result.get(0) : null;
    }

    private void updateLastCodeByClass(boolean resetLast, IdentifierEntity classEntity) {
        if (!ObjectUtil.isEmpty(classEntity)) {
            TyplmLoggerUtil.debug(log, () -> "updateLastCodeByClass  ==>  classEntity =【{}】", () -> new Object[]{classEntity});
            TyplmCodeBaseDO codeBaseDO = this.queryCodeBaseDOByBaseoid(classEntity.getOid(), classEntity.getOtype());
            if (codeBaseDO != null && !ObjectUtil.isEmpty(codeBaseDO)) {
                TyplmLoggerUtil.debug(log, () -> "updateLastCodeByClass  ==>  codeBaseDO =【{}】", () -> new Object[]{codeBaseDO});
                if (resetLast) {
                    codeBaseDO.setLastcode("");
                } else {
                    codeBaseDO.setLastcode(this.generateCodeByLastCode(classEntity));
                }

                TyplmLoggerUtil.debug(log, () -> "updateLastCodeByClass  ==>  codeBaseDO =【{}】", () -> new Object[]{codeBaseDO});
                TyplmEntityBaseUtil.fillCommonFieldForUpdate(codeBaseDO);
                this.typlmCodeBaseMapper.updateByPrimaryKey(codeBaseDO);
            }
        }
    }

    private String generateCodeByLastCode(IdentifierEntity classificationInfo) {
        if (ObjectUtil.isEmpty(classificationInfo)) {
            return "";
        } else {
            TyplmClassificationCodeVo classificationCodeVo = this.getCodeRefInfoByObjectBaseOID(classificationInfo);
            return this.generateCodeByClassLastCode(classificationCodeVo);
        }
    }

    private TyplmClassificationCodeVo getCodeRefInfoByObjectBaseOID(IdentifierEntity identifierEntity) {
        TyplmClassificationCodeVo classificationCodeVo = new TyplmClassificationCodeVo();
        TyplmCodeBaseDTO codeBaseDO = this.queryCodeBaseDTOByBaseoid(identifierEntity);
        if (ObjectUtil.isNotEmpty(codeBaseDO)) {
            classificationCodeVo.setCodeBaseDTO(codeBaseDO);
        }

        List<TyplmCodeSerialDTO> codeSerialDTOList = this.queryCodeSerialByBaseOID(identifierEntity);
        if (CollUtil.isNotEmpty(codeSerialDTOList)) {
            classificationCodeVo.setCodeSerialDTOList(codeSerialDTOList);
        }

        classificationCodeVo.setIdentifierEntity(identifierEntity);
        return classificationCodeVo;
    }

    private String generateCodeByClassLastCode(TyplmClassificationCodeVo item) {
        StringBuilder code = new StringBuilder(8);
        TyplmCodeBaseDTO itemInfo = item.getCodeBaseDTO();
        if (ObjectUtil.isNotEmpty(itemInfo)) {
            itemInfo = item.getCodeBaseDTO();
            if (StringUtil.isNotEmpty(itemInfo.getObjectnumber())) {
                code.append(itemInfo.getObjectnumber().trim());
            }

            if (StringUtil.isNotEmpty(itemInfo.getSeparator())) {
                code.append(itemInfo.getSeparator().trim());
            }
        }

        this.generateSerialLastCode(item, code);
        return code.toString();
    }

    private void generateSerialLastCode(TyplmClassificationCodeVo item, StringBuilder code) {
        if (CollUtil.isNotEmpty(item.getCodeSerialDTOList())) {
            Iterator<TyplmCodeSerialDTO> var3 = item.getCodeSerialDTOList().iterator();

            while(var3.hasNext()) {
                TyplmCodeSerialDTO itemSerial = var3.next();
                if (itemSerial.getS_type().equalsIgnoreCase("number")) {
                    code.append(this.generateNumberSerialLastCode(itemSerial));
                } else if (itemSerial.getS_type().equalsIgnoreCase("date")) {
                    code.append(itemSerial.getS_lastcode());
                } else if (itemSerial.getS_type().equalsIgnoreCase("customization")) {
                    code.append(this.generateCustomSerialLastCode(itemSerial));
                }

                if (StringUtil.isNotEmpty(itemSerial.getSeparator())) {
                    code.append(itemSerial.getSeparator());
                }
            }
        }
    }

    private String generateNumberSerialLastCode(TyplmCodeSerialDTO itemInfo) {
        StringBuilder serialCode = new StringBuilder(8);
        StringBuilder format = new StringBuilder(8);

        for(int i = 0; i < itemInfo.getS_len(); ++i) {
            format.append("0");
        }

        if (StringUtil.isNotEmpty(itemInfo.getS_lastcode())) {
            String value = itemInfo.getS_lastcode();
            Integer valueData = Integer.parseInt(value);
            String code = NumberUtil.decimalFormat(format.toString(), valueData);
            serialCode.append(code);
        }

        return serialCode.toString();
    }

    private String generateCustomSerialLastCode(TyplmCodeSerialDTO itemInfo) {
        if (!StringUtils.hasText(itemInfo.getS_lastcode())) {
            return "";
        } else {
            StringBuilder code = new StringBuilder(8);
            List<Integer> indexList = this.getCustomizationSerialLastCode(itemInfo.getS_lastcode());
            List<TyplmCodeCustomizationStreamVO> serialData = this.getCustomizationStremData(itemInfo);
            this.getCustomCodeByIndex(serialData, indexList, code);
            return code.toString();
        }
    }

    private List<Integer> getCustomizationSerialLastCode(String lastCode) {
        List<Integer> result = new ArrayList<>();
        if (!StringUtil.isNotEmpty(lastCode)) {
            return result;
        } else {
            String[] data = lastCode.split(",");
            if (data != null) {
                String[] var4 = data;
                int var5 = data.length;

                for(int var6 = 0; var6 < var5; ++var6) {
                    String indexStr = var4[var6];
                    if (this.isNumber(indexStr)) {
                        result.add(Integer.parseInt(indexStr));
                    }
                }
            }

            return result;
        }
    }

    private List<TyplmCodeCustomizationStreamVO> getCustomizationStremData(TyplmCodeSerialDTO info) {
        return (List)(!StringUtils.hasText(info.getS_customer()) ? new ArrayList() : JSON.parseArray(info.getS_customer(), TyplmCodeCustomizationStreamVO.class));
    }

    private Boolean getCustomCodeByIndex(List<TyplmCodeCustomizationStreamVO> serialData, List<Integer> indexList, StringBuilder code) {
        boolean result = false;

        for(int i = indexList.size() - 1; i >= 0; --i) {
            if (indexList.get(i) < serialData.size() && indexList.get(i) >= 0) {
                code.insert(0, serialData.get(indexList.get(i)).getKey());
            } else {
                code.insert(0, serialData.get(0).getKey());
            }
        }

        result = true;
        Iterator<Integer> var7 = indexList.iterator();

        while(var7.hasNext()) {
            int index = var7.next();
            if (index < serialData.size() - 1) {
                result = false;
            }
        }

        return result;
    }

    private boolean isNumber(String str) {
        Pattern pattern = Pattern.compile("[0-9]*");
        return pattern.matcher(str).matches();
    }
}
